import MASS.*;             // Library for Multi-Agent Spatial Simulation
import java.util.*;        // for Vector
import java.awt.*;         // uses the abstract windowing toolkit
import java.awt.event.*;   // also uses key events so we need this

public class massHelloWorldConcise extends Place {
  // constants
  public static final int init_ = 0;

  public static final int startGraphics_ = 4;
  public static final int writeToGraphics_ = 5;
  public static final int finishGraphics_ = 6;
  public static final int computeTime_ = 8;
  public static final int collectTime_ = 9;
  public long currentTime;

  private int sizeX, sizeY;

  
  public massHelloWorldConcise( Object interval ) {

  }
  
  
  public Object callMethod( int funcId, Object args ) {
	switch( funcId ) {
	  case init_: return init( args );

	  case startGraphics_: return startGraphics( args );
	  case writeToGraphics_: return writeToGraphics( args );
	  case finishGraphics_: return finishGraphics( args );

          case computeTime_ : return computeTime( args );
          case collectTime_ : return collectTime(args);
	}
	return null;
  }
  
  public Object computeTime( Object args ) {
      currentTime = System.currentTimeMillis();

      return null;
  }

  
  // --------------------------------------------------------------------------
  /** 
   * Since size[] and index[] are not yet set by
   * the system when the constructor is called, this init( ) method must
   * be called "after" rather than "during" the constructor call
   * @param args formally declared but actually not used
   */
  public Object init( Object args ) {
	sizeX = size[0]; sizeY = size[1]; // size  is the base data members

	
	return null;
  }

//  /** 
//   * Return the local wave height to the cell[0,0]
//   * @param args formally declared but actually not used.
//   */
//  public Double collectWave( Object args ) {
//	return new Double( wave[2] ); 
//  }
  public Long collectTime(Object args) {
      return new Long(currentTime);
  }
//  
  // Graphics --------------------------------------------------------------------------
  private static final int defaultN = 100; // the default system size
  private static final int defaultCellWidth = 8;
  private static Color bgColor;            //white background
  private static Frame gWin;               // a graphics window
  private static int cellWidth;            // each cell's width in the window
  private static Insets theInsets;         // the insets of the window 
  private static Color wvColor[];          // wave color
  private static int N = 0;                // array size
  
  // start a graphics window ------------------------------------------------------
  public Object startGraphics( Object args ) {
	// define the array size
	N = size[0];
	N = 100;
	// Graphics must be handled by a single thread
	bgColor = new Color( 200, 255, 200 );//white background
	
	// the cell width in a window
	cellWidth = (int)((double) defaultCellWidth / ((double) N / (double) defaultN )); //mod by John
	if ( cellWidth == 0 )
	  cellWidth = 1;
	
	// initialize window and graphics:
	gWin = new Frame( "MASS Hello World" );
	gWin.setLocation( 50, 50 );  // screen coordinates of top left corner
	
	gWin.setResizable( false );
	gWin.setVisible( true );     // show it!
	theInsets = gWin.getInsets();
	Dimension frameDim = new Dimension (N * cellWidth + theInsets.left + theInsets.right,
										N * cellWidth + theInsets.top + theInsets.bottom);
	gWin.setSize(frameDim);
	
	// wait for frame to get initialized
	long resumeTime = System.currentTimeMillis() + 1000;
	do {} while (System.currentTimeMillis() < resumeTime);
	
	// paint the back ground
	Graphics g = gWin.getGraphics( );
	g.setColor( bgColor );
	g.fillRect( theInsets.left,
			   theInsets.top,
			   N * cellWidth,
			   N * cellWidth );
	
	// prepare cell colors
	wvColor = new Color[21];
	wvColor[0] = new Color( 0x0000FF );   // blue
	wvColor[1] = new Color( 0x0033FF );
	wvColor[2] = new Color( 0x0066FF );
	wvColor[3] = new Color( 0x0099FF );
	wvColor[4] = new Color( 0x00CCFF );
	wvColor[5] = new Color( 0x00FFFF );
	wvColor[6] = new Color( 0x00FFCC );
	wvColor[7] = new Color( 0x00FF99 );
	wvColor[8] = new Color( 0x00FF66 );
	wvColor[9] = new Color( 0x00FF33 );
	wvColor[10] = new Color( 0x00FF00 );  // green
	wvColor[11] = new Color( 0x33FF00 );
	wvColor[12] = new Color( 0x66FF00 );
	wvColor[13] = new Color( 0x99FF00 );
	wvColor[14] = new Color( 0xCCFF00 );
	wvColor[15] = new Color( 0xFFFF00 );
	wvColor[16] = new Color( 0xFFCC00 );
	wvColor[17] = new Color( 0xFF9900 );
	wvColor[18] = new Color( 0xFF6600 );
	wvColor[19] = new Color( 0xFF3300 );
	wvColor[20] = new Color( 0xFF0000 );  // red
	
	gWin.setLocation( 0, 0 ); //mod by John, debug line
	return null;
  }
  
  // update a graphics window with new cell information -------------------------------------
  public Object writeToGraphics( Object arg_waves ) {
//	Object[] waves = ( Object[] )arg_waves;
        System.err.println("DEFINING GRAPHICS OBJECT of (x,Y) " + sizeX + " " + sizeY);
	Graphics g = gWin.getGraphics( );
	for ( int i = 0; i < sizeX; i++  ) 
	  for ( int j = 0; j < sizeY; j++ ) {               
                int index = (int)((currentTime/500) % 21);
                             
		// show a cell
		g.setColor( wvColor[index] );
		g.fill3DRect( theInsets.left + i * cellWidth,
					 theInsets.top  + j * cellWidth,
					 cellWidth, cellWidth, true ); //mod by John
	  }
	return null;
  }
  
  // finish the graphics window -------------------------------------
  public Object finishGraphics( Object args ) {
	Graphics g = gWin.getGraphics( );
	g.dispose( );
	gWin.removeNotify( );
	gWin = null;
	
	return null;
  }
  
  // --------------------------------------------------------------------------
  /** 
   * Starts a Wave2 application with the MASS library.
   * @param receives the array size, the maximum simulation time, the graphic
   *        updating time, the number of processes to spawn, and the
   *        number of threads to create.
   */
  public static void main( String[] args ) throws Exception 
  {

        String login;// = args[0];
        String password;// = args[1];
        String port;// = args[2];
	int size;// = Integer.parseInt( args[3] );
	int maxTime;// = Integer.parseInt( args[4] );
	int interval;// = Integer.parseInt( args[5] );
	int nProcesses;// = Integer.parseInt( args[6] );
	int nThreads;// = Integer.parseInt( args[7] );
//        boolean showGraphics = args.length == 9 ? true : false;
        
           login = "dslab444";
        password = "dslab-302444";
        port = "12345";
        size = 200;
        maxTime = 5000;
        interval = 47;
        nProcesses = 2;
        nThreads = 8;

	// start MASS
	String[] massArgs = new String[4];
	massArgs[0] = login;            // user name
	massArgs[1] = password;          // password
        massArgs[2] = "machinefile.txt";    // machine file
        massArgs[3] = port;
        System.err.println("INITIALIZING MASS"); 
	MASS.init( massArgs, nProcesses, nThreads ); 
	
	// create a Wave2D array
	Places computeTimeHelloWorld = new Places( 1, "massHelloWorldConcise", ( Object )( new Integer( interval ) ), size, size );
        System.err.println("CALLING ALL INIT"); 
	computeTimeHelloWorld.callAll( init_, null );
        
	
	// start graphics

        System.err.println("STARTING GRAPHICS");
	  computeTimeHelloWorld.callSome( startGraphics_, (Object)null, 0, 0 );

	// now go into a cyclic simulation
	for ( int time = 0; time < maxTime; time++ ) {

            System.err.println("CALL ALL ITERATION: " + time);
	  computeTimeHelloWorld.callAll( computeTime_, ( Object )( new Integer( time ) ) );


	
            if ( time % interval == 0 ) {
                System.err.println("AFTER COLLECT TIME ITERATION: " + time);
                Object[] times = computeTimeHelloWorld.callAll(collectTime_, null);

                 System.err.println("WRITE GRAPHICS ITERATION: " + time);   
                    computeTimeHelloWorld.callSome( writeToGraphics_, (Object)times, 0, 0 );
                    
            } 
	}
	
	   
        System.err.println("BEFORE FINISH GRAPHICS CALL ALL"); 
        //computeTimeHelloWorld.callAll( finishGraphics_, null );
        computeTimeHelloWorld.callSome( finishGraphics_, (Object) null, 0, 0 ); 
        System.err.println("AFTER FINISH GRAPHICS CALL ALL"); 
	
	MASS.finish( );
  }
}
